using System;
using ch.ethz.ssh2.crypto;
using ch.ethz.ssh2.transport;
using Org.BouncyCastle.Security;
namespace ch.ethz.ssh2.packets
{
	
	/// <summary> PacketKexInit.
	/// 
	/// </summary>
	/// <author>  Christian Plattner
	/// </author>
	/// <version>  2.50, 03/15/10
	/// </version>
	public class PacketKexInit
	{
		virtual public byte[] Payload
		{
			get
			{
				if (payload == null)
				{
					TypesWriter tw = new TypesWriter();
					tw.writeByte(Packets.SSH_MSG_KEXINIT);
					tw.writeBytes(kp.cookie, 0, 16);
					tw.writeNameList(kp.kex_algorithms);
					tw.writeNameList(kp.server_host_key_algorithms);
					tw.writeNameList(kp.encryption_algorithms_client_to_server);
					tw.writeNameList(kp.encryption_algorithms_server_to_client);
					tw.writeNameList(kp.mac_algorithms_client_to_server);
					tw.writeNameList(kp.mac_algorithms_server_to_client);
					tw.writeNameList(kp.compression_algorithms_client_to_server);
					tw.writeNameList(kp.compression_algorithms_server_to_client);
					tw.writeNameList(kp.languages_client_to_server);
					tw.writeNameList(kp.languages_server_to_client);
					tw.writeBoolean(kp.first_kex_packet_follows);
					tw.writeUINT32(kp.reserved_field1);
					payload = tw.getBytes();
				}
				return payload;
			}
			
		}
		virtual public KexParameters KexParameters
		{
			get
			{
				return kp;
			}
			
		}
		virtual public System.String[] Compression_algorithms_client_to_server
		{
			get
			{
				return kp.compression_algorithms_client_to_server;
			}
			
		}
		virtual public System.String[] Compression_algorithms_server_to_client
		{
			get
			{
				return kp.compression_algorithms_server_to_client;
			}
			
		}
		virtual public byte[] Cookie
		{
			get
			{
				return kp.cookie;
			}
			
		}
		virtual public System.String[] Encryption_algorithms_client_to_server
		{
			get
			{
				return kp.encryption_algorithms_client_to_server;
			}
			
		}
		virtual public System.String[] Encryption_algorithms_server_to_client
		{
			get
			{
				return kp.encryption_algorithms_server_to_client;
			}
			
		}
		virtual public bool First_kex_packet_follows
		{
			get
			{
				return kp.first_kex_packet_follows;
			}
			
		}
		virtual public System.String[] Kex_algorithms
		{
			get
			{
				return kp.kex_algorithms;
			}
			
		}
		virtual public System.String[] Languages_client_to_server
		{
			get
			{
				return kp.languages_client_to_server;
			}
			
		}
		virtual public System.String[] Languages_server_to_client
		{
			get
			{
				return kp.languages_server_to_client;
			}
			
		}
		virtual public System.String[] Mac_algorithms_client_to_server
		{
			get
			{
				return kp.mac_algorithms_client_to_server;
			}
			
		}
		virtual public System.String[] Mac_algorithms_server_to_client
		{
			get
			{
				return kp.mac_algorithms_server_to_client;
			}
			
		}
		virtual public int Reserved_field1
		{
			get
			{
				return kp.reserved_field1;
			}
			
		}
		virtual public System.String[] Server_host_key_algorithms
		{
			get
			{
				return kp.server_host_key_algorithms;
			}
			
		}
		internal byte[] payload;
		
		internal KexParameters kp = new KexParameters();
		
		public PacketKexInit(CryptoWishList cwl, SecureRandom rnd)
		{
			kp.cookie = new byte[16];
			rnd.NextBytes(kp.cookie);
			
			kp.kex_algorithms = cwl.kexAlgorithms;
			kp.server_host_key_algorithms = cwl.serverHostKeyAlgorithms;
			kp.encryption_algorithms_client_to_server = cwl.c2s_enc_algos;
			kp.encryption_algorithms_server_to_client = cwl.s2c_enc_algos;
			kp.mac_algorithms_client_to_server = cwl.c2s_mac_algos;
			kp.mac_algorithms_server_to_client = cwl.s2c_mac_algos;
			kp.compression_algorithms_client_to_server = new System.String[]{"none"};
			kp.compression_algorithms_server_to_client = new System.String[]{"none"};
			kp.languages_client_to_server = new System.String[]{};
			kp.languages_server_to_client = new System.String[]{};
			kp.first_kex_packet_follows = false;
			kp.reserved_field1 = 0;
		}
		
		public PacketKexInit(byte[] payload, int off, int len)
		{
			this.payload = new byte[len];
			Array.Copy(payload, off, this.payload, 0, len);
			
			TypesReader tr = new TypesReader(payload, off, len);
			
			int packet_type = tr.readByte();
			
			if (packet_type != Packets.SSH_MSG_KEXINIT)
				throw new System.IO.IOException("This is not a KexInitPacket! (" + packet_type + ")");
			
			kp.cookie = tr.readBytes(16);
			kp.kex_algorithms = tr.readNameList();
			kp.server_host_key_algorithms = tr.readNameList();
			kp.encryption_algorithms_client_to_server = tr.readNameList();
			kp.encryption_algorithms_server_to_client = tr.readNameList();
			kp.mac_algorithms_client_to_server = tr.readNameList();
			kp.mac_algorithms_server_to_client = tr.readNameList();
			kp.compression_algorithms_client_to_server = tr.readNameList();
			kp.compression_algorithms_server_to_client = tr.readNameList();
			kp.languages_client_to_server = tr.readNameList();
			kp.languages_server_to_client = tr.readNameList();
			kp.first_kex_packet_follows = tr.readBoolean();
			kp.reserved_field1 = tr.readUINT32();
			
			if (tr.remain() != 0)
				throw new System.IO.IOException("Padding in KexInitPacket!");
		}
	}
}